package com.kitty.game.safeLock.service;

import com.kitty.game.role.model.Role;
import com.kitty.game.enter.RespGeneralNotify;
import com.kitty.game.role.service.AccountService;
import com.kitty.game.role.service.RoleService;
import com.kitty.game.safeLock.message.ReqModifyPasswd;
import com.kitty.game.safeLock.message.ReqOpenSafeLockDlg;
import com.kitty.game.safeLock.message.ReqSetSafePasswd;
import com.kitty.game.safeLock.message.ReqUnlock;
import com.kitty.game.safeLock.message.RespModifyPasswdDlg;
import com.kitty.game.safeLock.message.RespSafeLockDlg;
import com.kitty.game.safeLock.message.RespSafeLockOpen;
import com.kitty.game.safeLock.message.RespSetSafeLockDlg;
import com.kitty.game.team.message.RespMsg;
import com.kitty.game.utils.Const;
import com.kitty.game.utils.NotifyModules;
import com.kitty.game.utils.TimeUtil;
import com.kitty.mina.cache.SessionUtils;
import com.kitty.mina.message.MessagePusher;
import org.apache.mina.core.session.IoSession;
import org.nutz.lang.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Service
public class SafeService {
    private final Logger logger = LoggerFactory.getLogger(SafeService.class);
    @Autowired
    RoleService roleService;
    @Autowired
    AccountService accountService;

    private ConcurrentMap<Long, ErrorRecord> errorRecords = new ConcurrentHashMap<>();

    /**
     * 设置安全密码
     *
     * @param session
     * @param reqSetSafePasswd
     */
    public void setSafePasswd(IoSession session, ReqSetSafePasswd reqSetSafePasswd) {
        logger.error("设置密码=={}=={}", reqSetSafePasswd.getKey(), reqSetSafePasswd.getPasswd());
        Role role = SessionUtils.getRoleBySession(session);
        if (role == null) {
            return;
        }

        if (!Strings.isEmpty(role.getSafePasswd())) {
            return;
        }
        role.setSafePasswd(reqSetSafePasswd.getPasswd());
        role.save();
        MessagePusher.pushMessage(session, new RespMsg("安全锁密码设置成功。"));
        role.setUnlock(true);
        MessagePusher.pushMessage(session, getLockStatus(role));
    }

    /**
     * 打开安全锁界面
     *
     * @param session
     * @param reqOpenSafeLockDlg
     */
    public void openSafeDlg(IoSession session, ReqOpenSafeLockDlg reqOpenSafeLockDlg) {
        Role role = SessionUtils.getRoleBySession(session);
        if (role == null) {
            return;
        }

        switch (reqOpenSafeLockDlg.getType()) {
            case "SafeLockMainDlg": //打开加锁界面
                if (!Strings.isEmpty(role.getSafePasswd())) {
                    MessagePusher.pushMessage(session, getLockStatus(role));
                } else {
                    MessagePusher.pushMessage(session, getLockStatus(role));
                }
                break;
            case "SafeLockSetDlg": //设置安全锁 先判断有没有安全锁密码 没有 返回设置界面
                if (!Strings.isEmpty(role.getSafePasswd())) {
                    return;
                }
                sendSetSafePasswd(session);
                break;
            case "SafeLockReleaseDlg": //呼出解锁界面
                sendPasswdInputDlg(role, getErrorNum(role));
                break;
            case "SafeLockModifyDlg":
                if (Strings.isEmpty(role.getSafePasswd())) {
                    MessagePusher.pushMessage(session, new RespMsg("你当前没有设置安全锁密码，请先设置安全锁密码。"));
                    return;
                }
                MessagePusher.pushMessage(session, new RespModifyPasswdDlg());
                break;
        }
    }


    public void sendSetSafePasswd(IoSession session) {
        RespSetSafeLockDlg respSetSafeLockDlg = new RespSetSafeLockDlg();
        respSetSafeLockDlg.setKey("jjVcYTA");
        MessagePusher.pushMessage(session, respSetSafeLockDlg);
    }

    /**
     * 取密码错误次数
     */
    public int getErrorNum(Role role) {
        int total = 0;
        long roleUid = role.getUid();
        long now = System.currentTimeMillis();
        if (errorRecords.containsKey(roleUid)) {
            long lastErrorTime = errorRecords.get(roleUid).lastErrorTime;
            if (now - lastErrorTime > 60 * TimeUtil.ONE_HOUR) {
                errorRecords.remove(roleUid);
            } else {
                total = errorRecords.get(roleUid).errorSum;
            }
        }
        return total;
    }

    /**
     * 验证解锁
     *
     * @param session
     * @param reqUnlock
     */
    public void unlock(IoSession session, ReqUnlock reqUnlock) {
        Role role = SessionUtils.getRoleBySession(session);
        if (role == null) {
            return;
        }

        long now = System.currentTimeMillis();

        int total = 0;
        long roleUid = role.getUid();
        if (errorRecords.containsKey(roleUid)) {
            long lastErrorTime = errorRecords.get(roleUid).lastErrorTime;
            if (now - lastErrorTime > 12 * TimeUtil.ONE_HOUR) {
                errorRecords.remove(roleUid);
            } else {
                total = errorRecords.get(roleUid).errorSum;
            }
        }
        if (total >= 5) {
            MessagePusher.pushMessage(session, new RespMsg("输入的错误密码次数超过限制。"));
            return;
        }
        if (reqUnlock.getPasswd().equals(role.getSafePasswd())) {
            //认证成功
            role.setUnlock(true);
            MessagePusher.pushMessage(session, new RespMsg("安全锁密码验证成功。"));
            MessagePusher.pushMessage(session, getLockStatus(role));
            closePasswdInputDlg(session);
        } else {
            errorRecords.putIfAbsent(roleUid, new ErrorRecord());
            errorRecords.get(roleUid).addErrorCount();
            errorRecords.get(roleUid).lastErrorTime = now;
            sendPasswdInputDlg(role, getErrorNum(role));
            MessagePusher.pushMessage(session, new RespMsg("密码输入错误，验证失败。"));
        }
    }

    public RespSafeLockDlg getLockStatus(Role role) {
        boolean isSet = !Strings.isEmpty(role.getSafePasswd());
        int endTime = getSafePasswdResetEndTime(role.getSafePasswdResetStartTime());
        RespSafeLockDlg respSafeLockDlg = new RespSafeLockDlg();
        respSafeLockDlg.setReset_days(Const.SAFE_PASSWORD_WAIT_RESET_DAY);
        respSafeLockDlg.setUnlock(role.isUnlock());
        respSafeLockDlg.setSet(isSet);
        respSafeLockDlg.setReset_start(role.getSafePasswdResetStartTime());
        respSafeLockDlg.setReset_end(endTime);
        return respSafeLockDlg;
    }

    /**
     * 认证调用
     *
     * @param role
     * @param errorNum
     */
    public void sendPasswdInputDlg(Role role, int errorNum) {
        RespSafeLockOpen respSafeLockOpen = new RespSafeLockOpen();
        respSafeLockOpen.setError_count_max((short) (5 - errorNum));
        MessagePusher.pushMessage(role, respSafeLockOpen);
    }

    /**
     * 关闭密码输入框 认证成功后发送
     *
     * @param session
     */
    public void closePasswdInputDlg(IoSession session) {
        RespGeneralNotify respGeneralNotify = new RespGeneralNotify();
        respGeneralNotify.setNotify((short) NotifyModules.NOTIFY_CLOSE_DLG); //关闭对话框
        respGeneralNotify.setValue("SafeLockReleaseDlg");
        MessagePusher.pushMessage(session, respGeneralNotify);
    }

    /**
     * 修改密码
     *
     * @param session
     * @param reqModifyPasswd
     */
    public void modifyPasswd(IoSession session, ReqModifyPasswd reqModifyPasswd) {
        logger.info("修改密码=={}==={}", reqModifyPasswd.getOldPasswd(), reqModifyPasswd.getNewPasswd());
        Role role = SessionUtils.getRoleBySession(session);
        if (role == null) {
            return;
        }

        if (role.getSafePasswd().equals(reqModifyPasswd.getOldPasswd())) {
            role.setSafePasswd(reqModifyPasswd.getNewPasswd());
            role.save();
            MessagePusher.pushMessage(session, new RespMsg("修改安全锁密码成功。"));
        } else {
            MessagePusher.pushMessage(session, new RespMsg("原始安全锁密码错误。"));
        }
    }

    /**
     * 申请重置
     *
     * @param role
     */
    public void reqReset(Role role) {
        /**没有设置安全锁时*/
        if (Strings.isEmpty(role.getSafePasswd())) {
            MessagePusher.pushMessage(role, new RespMsg("你当前没有设置安全锁密码，请先设置安全锁密码。"));
            return;
        }

        /**设置强制解锁开始时间*/
        int start = (int) (System.currentTimeMillis() / TimeUtil.ONE_SECOND);
        role.setSafePasswdResetStartTime(start);
        role.save();

        MessagePusher.pushMessage(role, getLockStatus(role));
    }

    /**
     * 取消重置
     *
     * @param role
     */
    public void cancelReset(Role role) {
        if (role.getSafePasswdResetStartTime() <= 0) {
            MessagePusher.pushMessage(role, new RespMsg("当前没有申请安全锁强制解除。"));
            return;
        }

        /**清除强制解锁开始时间*/
        role.setSafePasswdResetStartTime(0);
        role.save();

        MessagePusher.pushMessage(role, getLockStatus(role));

        MessagePusher.pushMessage(role, new RespMsg("取消安全锁强制解除状态成功。"));
    }

    /**
     * 获得安全锁重置结束时间
     *
     * @param resetStartTime
     * @return
     */
    private int getSafePasswdResetEndTime(int resetStartTime) {
        if (resetStartTime <= 0) {
            return 0;
        }

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(resetStartTime * TimeUtil.ONE_SECOND);

        /**当前小时 小于每日重置小时，则在强制解锁天数的前一天解锁，否则在强制天数的那天解锁*/
        if (calendar.get(Calendar.HOUR_OF_DAY) < Const.RESET_HOUR) {
            calendar.add(Calendar.DAY_OF_YEAR, Const.SAFE_PASSWORD_WAIT_RESET_DAY - 1);
        } else {
            calendar.add(Calendar.DAY_OF_YEAR, Const.SAFE_PASSWORD_WAIT_RESET_DAY);
        }

        calendar.set(Calendar.HOUR_OF_DAY, Const.RESET_HOUR);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        logger.warn("{}的安全锁重置结束时间：{}", TimeUtil.formatDate(new Date(resetStartTime * TimeUtil.ONE_SECOND), TimeUtil.DEFAULT_DATE_FORMAT), TimeUtil.formatDate(calendar.getTime(), TimeUtil.DEFAULT_DATE_FORMAT));

        return (int) (calendar.getTimeInMillis() / TimeUtil.ONE_SECOND);
    }

    /**
     * 检测是否进行安全锁重置
     *
     * @param role
     */
    public void checkSafePasswdReset(Role role) {
        if (role == null) {
            return;
        }

        int endTime = getSafePasswdResetEndTime(role.getSafePasswdResetStartTime());
        if (endTime <= 0) {
            return;
        }

        long now = System.currentTimeMillis();

        if ((now / TimeUtil.ONE_SECOND) >= endTime) {
            logger.warn("{}({})进行安全锁重置，重置时间为:{}", role.getUid(), role.getName(), TimeUtil.formatDate(new Date(endTime * TimeUtil.ONE_SECOND), TimeUtil.DEFAULT_DATE_FORMAT));
            role.setSafePasswdResetStartTime(0);
            role.setSafePasswd(null);
            role.save();

            MessagePusher.pushMessage(role, getLockStatus(role));
        }
    }
}

class ErrorRecord {

    int errorSum;

    long lastErrorTime;

    void addErrorCount() {
        this.errorSum++;
    }
}
